<#
  @brief  源串中如果有多个匹配的子串，可以指定替换掉哪一个匹配的子串
  @Notes  None.
  @param  $SRCSTR, 需要处理的原始字符串
  @param  $SUBSTR, 需要匹配的子串
  @param  $NEWSUBSTR, 新子串用于替换旧的
  @param  $N, 原始字符串中出现多个可匹配的子串时,指定哪一个子串被替换
  @retval 处理后的目标字符串
#>
function SubstrReplace([string]$SRCSTR, [string]$SUBSTR, [string]$NEWSUBSTR, [int]$N)
{
    [byte[]]$SrcArray = $SRCSTR.ToCharArray();
    [byte[]]$SubArray = $SUBSTR.ToCharArray();
    [byte[]]$NewSubArray = $NEWSUBSTR.ToCharArray();
    [byte[]]$RstArray = New-Object byte[] ($SRCSTR.Length+$NEWSUBSTR.Length);

    [int]$count = 0;
    [int[]]$SubstrIdx = New-Object int[] (64);  #数组预分配足量空间，避免越界报错
    [int]$SubstrIdx_i=0; 
    #首次遍历源串，获取子串匹配的源串字符起始索引，保存到数组中
    for($i = 0; $i -lt $SRCSTR.Length; $i++)
    {
        $count = 0;
        for($j=0; $j -lt $SUBSTR.Length; $j++){
            if($SrcArray[$i+$j] -ne $SubArray[$j]){
                break;
            }
            else{ $count++; }
        }
        if($count -eq $SUBSTR.Length){
            $SubstrIdx[$SubstrIdx_i] = $i;
            $SubstrIdx_i++;
        }
    }
    #二次遍历源串，匹配到指定位置的子串时，使用新的子串替换掉旧的子串
    [int]$rstc=0;
    for($i = 0; $i -lt $SRCSTR.Length;)
    {
        #Write-Host -NoNewLine " "([char]$SrcArray[$i]);  #Write-Host不换行显示整型数组中的变量,需要[char]显式转换为ASCII类型
        $count = 0;
        for($j=0; $j -lt $SUBSTR.Length; $j++)
        {
            if($SrcArray[$i+$j] -ne $SubArray[$j])
            {
                break;
            }
            else{ $count++; }
        }

        if(
            ($i -eq $SubstrIdx[$N-1]) -and  #子串匹配索引数组从0开始计数；调用函数时，习惯上从1开始
            ($count -eq $SUBSTR.Length))
        {
            
            for($k=0; $k -lt $NEWSUBSTR.Length; $k++)
            {
                $RstArray[$rstc] = $NewSubArray[$k];
                $rstc++;
            }
            $i+=$SUBSTR.Length;
        }else{
            $RstArray[$rstc] = $SrcArray[$i];
            $rstc++;
            $i++;
        }
    }
    #Write-Host;  #显示换行效果

    #ASCII字符数组转换为String类型
    return [System.Text.Encoding]::ASCII.GetString($RstArray);
}

########################### 函数测试 ##############################
$Original = "li jin quan li jinquanli"
Write-Host $Original
Write-Host ----------------------------------------

$RSTSTR = SubstrReplace $Original "li" "@~@" 1
Write-Host $RSTSTR

$RSTSTR = SubstrReplace $Original "li" "@~@" 2
Write-Host $RSTSTR

$RSTSTR = SubstrReplace $Original "li" "@~@" 3
Write-Host $RSTSTR